// 存储状态的数组
let state = []
// 存储状态更新函数的数组
let setters = []
// 存储副作用的数组
let effects = []
// 当前状态索引
let stateIndex = 0

// 当前副作用索引
let effectIndex = 0

// 创建状态更新函数
function createSetter(index) {
    return function (newState) {
        // 如果是函数形式，传入当前状态计算新状态
        if (typeof newState === 'function') {
            state[index] = newState(state[index])
        } else {
            state[index] = newState
        }
        // 状态更新后重新渲染
        render()
    }
}

// 模拟useState
function useState(initialState) {
    // 保存当前索引，因为后续stateIndex会变化
    const currentIndex = stateIndex

    // 初始化状态：如果已有状态则复用，否则使用初始值
    state[currentIndex] =
        state[currentIndex] !== undefined ? state[currentIndex] : initialState

    // 创建并存储更新函数
    if (!setters[currentIndex]) {
        setters[currentIndex] = createSetter(currentIndex)
    }

    // 准备下一个状态的索引
    stateIndex++

    // 返回当前状态和对应的更新函数
    return [state[currentIndex], setters[currentIndex]]
}

// 模拟useEffect
function useEffect(callback, dependencies) {
    // 保存当前副作用索引
    const currentIndex = effectIndex

    // 检查是否有依赖项变化
    const hasChanged = () => {
        // 如果没有提供依赖项数组，每次渲染都认为变化了
        if (!dependencies) return true

        // 获取上一次的依赖项
        const prevDeps = effects[currentIndex]?.dependencies

        // 如果是第一次执行，也认为变化了
        if (!prevDeps) return true

        // 对比新旧依赖项是否有变化
        return dependencies.some((dep, i) => dep !== prevDeps[i])
    }

    // 如果依赖项有变化，才执行副作用
    if (hasChanged()) {
        // 保存清理函数
        const cleanup = callback()

        // 存储当前副作用的信息：清理函数和依赖项
        effects[currentIndex] = {
            cleanup,
            dependencies: dependencies ? [...dependencies] : undefined
        }
    }

    // 准备下一个副作用的索引
    effectIndex++
}

// 渲染函数
function render() {
    // 重置索引，确保每次渲染时钩子调用顺序一致
    stateIndex = 0
    effectIndex = 0
    ReactDOM.render(<App />, document.getElementById('root'))
}

function App() {
    const [count, setCount] = useState(0)
    const [name, setName] = useState('张三')

    // 模拟副作用：当count变化时执行
    useEffect(() => {
        console.log(`count发生变化: 新值为${count}`)
        // 清理函数：组件卸载或count再次变化前执行
        return () => console.log(`清理count副作用: 旧值为${count}`)
    }, [count])

    // 模拟副作用：当name变化时执行
    useEffect(() => {
        console.log(`name发生变化: 新值为${name}`)
        return () => console.log(`清理name副作用: 旧值为${name}`)
    }, [name])

    return (
        <div>
            {count}
            <button onClick={() => setCount(count + 1)}>setCount</button>
            {name}
            <button onClick={() => setName('李四')}>setName</button>
        </div>
    )
}
